package com.oocl.homework.crm.datastruct;



public class MyLinkedList<T extends MyCompareable<T>> {
	
	private Node<T> header;
	private Node<T> tail;
	private int size;
	
	
	public MyLinkedList(){
		header = null;
		tail = null;
		size = 0;
	}
	
	public int getSize(){
		return size;
	}
	
	public void add(T t){
		if (size==0) {
			Node<T> node = new Node<>(null, null, t);
			header = node;
			tail = node;
			size++;
		}else{
			Node<T> node = new Node<>(tail, null, t);
			tail.next = node;
			tail = node;
			size++;
		}
	}
	
	public void addWithIndex(T t,int index) throws Exception{
		if(index>=size) throw new Exception("out of boundary");
		
		if (index ==0) {
			Node<T> node = header;
			Node<T> newNode = new Node<>(null, node, t);
			node.pre = newNode;
			header = newNode;
			
		}else if (index == size-1) {
			Node<T> node = tail;
			Node<T> pre = tail.pre;
			Node<T> newNode = new Node<>(node.pre, tail, t);
			pre.next = newNode;
			tail.pre = newNode;
		}else{
			Node<T> node = header;
			for (int i = 0; i <index; i++) {
				 node = node.next;
			}
			Node<T> pre = node.pre;
			Node<T> newNode = new Node<>(node.pre, node, t);
			pre.next = newNode;
			node.pre = newNode;
		}
		size++;
	}
	
	
	public void deleteWithIndex(int index) {
		if(index>=size) {
			System.out.println("out of array boundary");
			return;
		}
		
		if (index ==0) {
			header = header.next;
			header.pre = null;
		}else if (index == size-1) {
			tail = tail.pre;
			tail.next = null;
		}else{
			Node<T> node = header;
			for (int i = 0; i <index; i++) {
				 node = node.next;
			}
			Node<T> pre = node.pre;
			Node<T> next = node.next;
			pre.next = next;
			next.pre = pre;
		}
		size--;
	}
	

	public T  get(int index){
		return getNode(index).item;
	}
	
	
	private Node<T> getNode(int index){
		Node<T> node = header;
		for (int i = 0; i <index; i++) {
			 node = node.next;
		}
		
		return node;
	}
	
//	
//	public void sortById() throws Exception{
//		
//		for (int i = 0; i < size; i++) {
//			for (int j = 0; j < size-i-1; j++) {
//				if (getNode(j).item.compareIdTo(getNode(j+1).item)>0) {
//					Node<T> pre = getNode(j+1);
//					deleteWithIndex(j+1);
//					addWithIndex((T) pre.item, j);
//				}
//			}
//		}
//	}
//	
//	public void sortByName() throws Exception{
//		for (int i = 0; i < size; i++) {
//			for (int j = 0; j < size-i-1; j++) {
//				if (getNode(j).item.compareNameTo(getNode(j+1).item)>0) {
//					Node<T> pre = getNode(j+1);
//					deleteWithIndex(j+1);
//					addWithIndex((T) pre.item, j);
//				}
//			}
//		}
//	}
	
	public int searchPosition(T t){
		Node<T> node = header;
		int count = 0;
		int position = -1;
		while (node!=null) {
			if(node.item.meetTo(t)==1)
				position = count;
				count++;
				node = node.next;
		}
		return position;
		
	}
	
	public String search(T t){
		Node<T> node = header;
		StringBuffer stringBuffer = new StringBuffer();
		while (node!=null) {
			if(node.item.meetTo(t)==1)
				stringBuffer.append(node.item.toString()+"\n");
			node = node.next;
		}
		return stringBuffer.toString();
		
	}
	
	public void replace(T t){
		Node<T> node = header;
		while (node!=null) {
			if(node.item.equals(t))
				node.item = t;
			node = node.next;
		}
		
	}
	
	public T getWithId(T t){
		Node<T> node = header;
		while (node!=null) {
			if(node.item.equals(t))
				return node.item;
			node = node.next;
		}
		return null;
	}
	
	private class Node<T>{
		private Node<T> pre;
		private Node<T> next;
		private T item;
		
		public Node(Node<T> pre, Node<T> next, T t) {
			super();
			this.pre = pre;
			this.next = next;
			this.item = t;
		}
		
		
		
	}
	
	public String toString(){
			StringBuffer stringBuffer = new StringBuffer();
			Node<T> node = header;
			while (node!=null) {
				stringBuffer.append(node.item.toString()+"\n");
				node = node.next;
			}
			return stringBuffer.toString();
	}
	
	
			
}
